/* NOTICE
    OpenJaWS - Open Java Weather Station
    
    Copyright (C) 2008 Grant Gardner <grant@lastweekend.com.au>
    
    OpenJaWS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
NOTICE */

package au.com.lastweekend.openjaws.api;

import java.util.Date;

import au.com.lastweekend.openjaws.units.WindUnit;

/**
 * Adds a wind_direction to current/min/max windspeed.
 * 
 * @author ggardner
 * 
 */
public class WindCurrentMinMax extends CurrentMinMax {

    public WindCurrentMinMax(WindCurrentMinMax object) {

        super(object);
        if (object == null) {
            this.setCurrent(WindUnitValue.NULL, null);
            this.setMaximum(WindUnitValue.NULL, null);
            this.setMinimum(WindUnitValue.NULL, null);
            this.clean();
        }
    }

    public WindCurrentMinMax() {

        this(null);
    }

    /**
     * average the current reading with a next reading
     * 
     * @param next
     * @param totalTime
     *            represented by the current reading
     * @param timeDiff
     *            between currentAverage and the next reading
     * @param readingTime
     *            time that param next was taken
     */
    public void average(WindCurrentMinMax next, long totalTime, long timeDiff, Date readingTime) {

        double currentSpeed = getCurrent().getValue();
        WindUnit currentSpeedUnit = (WindUnit) getCurrent().getUnit();

        double nextDirection = getCurrent().getDirection();

        // convert to same unit as current
        WindUnitValue nextUnitValue = next.getCurrent().convertTo((WindUnit) currentSpeedUnit);

        double nextValue = nextUnitValue.getValue();
        double accumValue = (currentSpeed * totalTime) + (timeDiff * nextValue);
        double newValue = accumValue / (totalTime + timeDiff);

        // We can't average direction in the same sense so just use the instantaneous value
        // ie the average of 15deg NNE and 345deg NNW is 180 S, probably not what we want
        // also swings of more than 60deg are described as variable, so lets leave that
        // to another plugin

        // First set the actual reading so we keep the true min/max
        setCurrent(nextValue, currentSpeedUnit, nextDirection, readingTime);
        // Now store the new average
        setCurrent(newValue, currentSpeedUnit, nextDirection);
    }

    public void setCurrent(double current, WindUnit unit, double direction) {

        super.setCurrent(new WindUnitValue(current, unit, direction), null);

    }

    public void setCurrent(double current, WindUnit unit, double direction, Date readingTime) {

        super.setCurrent(new WindUnitValue(current, unit, direction), readingTime);
    }

    @Override
    public WindUnitValue getCurrent() {

        return (WindUnitValue) super.getCurrent();
    }

    @Override
    protected UnitValue protectNull(UnitValue uv) {

        if (uv == null) {
            return WindUnitValue.NULL;
        } else {
            return uv;
        }
    }

    public void setMaximum(double maximum, WindUnit unit, double dirMaximum, Date timeMaximum) {

        super.setMaximum(new WindUnitValue(maximum, unit, dirMaximum), timeMaximum);

    }

    public void setMinimum(double minimum, WindUnit unit, double dirMinimum, Date timeMinimum) {

        super.setMinimum(new WindUnitValue(minimum, unit, dirMinimum), timeMinimum);
    }

    public void setMaximum(double maximum, WindUnit unit, Date timeMaximum) {

        super.setMaximum(new WindUnitValue(maximum, unit), timeMaximum);
    }

    public void setMinimum(double minimum, WindUnit unit, Date timeMinimum) {

        super.setMinimum(new WindUnitValue(minimum, unit), timeMinimum);
    }

}
